package com.shelpe.services.algorithm.ranking;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shelpe.services.algorithm.client.RankClient;
import com.shelpe.services.algorithm.controller.RankingController;
import com.shelpe.services.algorithm.entity.batis.Keyword;
import com.shelpe.services.algorithm.entity.batis.KeywordExample;
import com.shelpe.services.algorithm.entity.jpa.Adgroup;
import com.shelpe.services.algorithm.entity.jpa.WantRank;
import com.shelpe.services.algorithm.repository.batis.KeywordMapper;
import com.shelpe.services.algorithm.repository.jpa.AdgroupRepository;
import com.shelpe.services.algorithm.repository.jpa.WantRankRepository;
import com.shelpe.services.algorithm.service.RealtimeRankService;
import com.shelpe.services.algorithm.sustain.SustainRule;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class RankingSustainRule implements SustainRule<RankingSustainer> {

	@Autowired
	private KeywordRankingSustainRule rule;
	@Autowired
	private RealtimeRankService realtimeRankService;
	@Autowired
	private WantRankRepository wantRankRepository;
	@Autowired
	private KeywordMapper keywordMapper;
	@Autowired
	private AdgroupRepository adgroupRepository;

	@Override
	public boolean check(RankingSustainer entity) {
		return StringUtils.isNotBlank(entity.getTactics().getKeywordIDs());
	}

	@Override
	public boolean prepare(RankingSustainer entity) {
		entity.setWantRanks(new ArrayList<WantRank>());
		String[] kids = entity.getTactics().getKeywordIDs().split(",");
		for (String kid : kids) {
			long id = NumberUtils.toLong(kid);
			if (id > 0) {
				WantRank rank = this.wantRankRepository
						.findOne(new WantRank.WantRankPK(entity.getTactics().getTacticsID(), id));
				if (rank != null) {
					entity.getWantRanks().add(rank);
				}
			}
		}
		if (entity.getWantRanks().size() == 0) {
			log.error("no ranks: {}", entity.getTactics());
			return false;
		}

		KeywordExample ke = new KeywordExample();
		ke.setUserId(entity.getTactics().getUserID());
		List<Long> keywordIDs = new ArrayList<Long>();
		for (WantRank rank : entity.getWantRanks()) {
			if(rank != null && rank.getKeywordID() > 0){
				keywordIDs.add(rank.getKeywordID());
			}
		}
		if(keywordIDs.size() > 0){
			ke.createCriteria().andKeywordIdIn(keywordIDs);
			List<Keyword> keywords = this.keywordMapper.selectByExample(ke);
			entity.setKeywords(keywords);
		}
		
		if (entity.getKeywords() == null || entity.getKeywords().size() == 0) {
			log.error("no keywords: {}", entity.getTactics());
			return false;
		}
		if (entity.getKeywords().iterator().next().getAdgroupId() != null) {
			long adgroupID = entity.getKeywords().iterator().next().getAdgroupId();
			Adgroup adgroup = this.adgroupRepository.findOne(adgroupID);
			if (adgroup == null) {
				log.error("adgroup not found: {}", entity.getTactics());
				return false;
			}
			entity.setAdgroupID(adgroupID);
			entity.setNick(adgroup.getNick());
			entity.setProductID(adgroup.getProductID());

			entity.setRanks(new ArrayList<RankClient.KeywordRealtimeRankItem>());
			keywordIDs = new ArrayList<Long>();
			for (Keyword kw : entity.getKeywords()) {
				keywordIDs.add(kw.getKeywordId());
			}
			entity.setRanks(this.realtimeRankService.syncRanks(adgroup.getNick(), adgroup.getAdgroupID(), keywordIDs));
			if (entity.getRanks().size() == 0) {
				log.error("no realtime rank: {}", entity.getTactics());
			}
		}

		return true;
	}

	@Override
	public SustainRule.SustainStatus sustain(RankingSustainer entity) {

		entity.setResults(new ArrayList<RankingController.RankingResult>());
		for (WantRank wr : entity.getWantRanks()) {
			KeywordRankingSustainer sustainer = new KeywordRankingSustainer();
			sustainer.setTactics(entity.getTactics());
			sustainer.setProductID(entity.getProductID());
			sustainer.setNick(entity.getNick());
			sustainer.setAdgroupID(entity.getAdgroupID());
			sustainer.setRank(wr);
			sustainer.setKeyword(entity.findKeywordByKeywordID(wr.getKeywordID()));
			sustainer.setCurrentItem(entity.findRankByKeywordID(wr.getKeywordID()));
			this.execute(sustainer);
			entity.getResults().add(sustainer.getResult());
		}

		return SustainRule.SustainStatus.keep;
	}

	private boolean execute(KeywordRankingSustainer sustainer) {
		log.info("start execute {} word ranking", sustainer.getTactics());
		boolean res = false;

		boolean continued = this.rule.check(sustainer);
		if (continued) {
			continued = this.rule.prepare(sustainer);
			if (continued) {
				SustainStatus status = this.rule.sustain(sustainer);
				if (status != SustainStatus.exceptional) {
					this.rule.maintain(sustainer, status);
					this.rule.mark(sustainer);
					res = true;
					log.debug("finish execute {} word ranking", sustainer.getTactics());
				} else {
					log.info("{} word fail to sustain", sustainer.getTactics());
				}
			} else {
				log.info("{} word is not ready", sustainer.getTactics());
			}
		} else {
			log.info("{} word does not need execute", sustainer.getTactics());
		}
		return res;
	}

	@Override
	public boolean maintain(RankingSustainer entity, SustainRule.SustainStatus status) {
		return true;
	}

	@Override
	public boolean mark(RankingSustainer entity) {
		return true;
	}

}
